# storage/file_manager.py 

import os
from .page import PAGE_SIZE


class FileManager:
    """
    管理与磁盘文件的交互，执行页面的读写操作。
    """

    def __init__(self, db_file_path: str):
        self.db_file_path = db_file_path
        self.db_file = None

        # --- 核心修正 1：采用更健壮的文件处理方式 ---
        # 如果数据库文件不存在，则先创建一个空文件。
        if not os.path.exists(self.db_file_path):
            open(self.db_file_path, 'w').close()

        # 使用 'r+b' 模式打开文件。这是进行随机读写的标准二进制模式。
        self.db_file = open(self.db_file_path, 'r+b')
        # --- 修正结束 ---

    def read_page(self, page_id: int) -> bytes:
        """从磁盘文件中读取一个页面。"""
        offset = page_id * PAGE_SIZE
        self.db_file.seek(offset)
        page_data = self.db_file.read(PAGE_SIZE)
        return page_data

    def write_page(self, page_id: int, data: bytes):
        """将一个页面的数据写入磁盘文件。"""
        offset = page_id * PAGE_SIZE
        self.db_file.seek(offset)
        self.db_file.write(data)
        # 每次写入后都强制刷新，确保数据离开Python的缓冲区
        self.db_file.flush()

    def allocate_page(self) -> int:
        """分配一个新页面，返回其 page_id。"""
        self.db_file.seek(0, os.SEEK_END)
        file_size = self.db_file.tell()
        new_page_id = file_size // PAGE_SIZE
        # 扩展文件以容纳新页面
        self.db_file.write(bytes(PAGE_SIZE))
        self.db_file.flush()
        return new_page_id

    def close(self):
        """关闭数据库文件，并强制将所有操作系统缓存同步到磁盘。"""
        if self.db_file:
            # --- 核心修正 2：强制同步到物理磁盘 ---
            self.db_file.flush()
            # os.fsync() 是一个底层命令，告诉操作系统：“把这个文件相关的
            # 所有待写入的缓存数据，立刻、马上写入物理硬盘！”
            os.fsync(self.db_file.fileno())
            # --- 修正结束 ---
            self.db_file.close()
            self.db_file = None

    def __del__(self):
        # 当对象被垃圾回收时，也尝试关闭文件，以防万一
        self.close()